package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.annotation.ChromeOSOnly
import io.shuttle.mbe.api.annotation.PromiseStyleMinVersion
import io.shuttle.mbe.api.types.ArrayBuffer
import io.shuttle.mbe.api.types.SubtleCrypto
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.VoidFunction
import io.shuttle.mbe.core.Promise

interface Enterprise {
    ////////////////////
    // Enterprise Device Attributes
    ////////////////////
    /**
     * Use the `Browser.enterprise.deviceAttributes` API to read device attributes.
     *
     * Permissions: "enterprise.deviceAttributes"
     *
     * Note: Only available to policy installed extensions.
     * @platform ChromeOS only
     * @since Chrome 46
     */
    interface DeviceAttributes {
        // Fetches the administrator-annotated Location.
        // If the current user is not affiliated or no Annotated Location has been set by the administrator,
        // returns an empty string.
        // @return {callback.annotatedLocation}
        @ChromeMinVersion(66)
        @PromiseStyleMinVersion(96)
        fun getDeviceAnnotatedLocation(
            callback: Value1Function<String>? = null
        ): Promise<String>

        // Fetches the administrator-annotated Asset Id.
        // If the current user is not affiliated or no Asset Id has been set by the administrator,
        // returns an empty string.
        // @return {callback.assetId}
        @ChromeMinVersion(66)
        @PromiseStyleMinVersion(96)
        fun getDeviceAssetId(
            callback: Value1Function<String>? = null
        ): Promise<String>

        // Fetches the device's hostname as set by DeviceHostnameTemplate policy.
        // If the current user is not affiliated or no hostname has been set by the enterprise policy,
        // returns an empty string.
        // @return {callback.hostname}
        @ChromeMinVersion(82)
        @PromiseStyleMinVersion(96)
        fun getDeviceHostname(
            callback: Value1Function<String>? = null
        ): Promise<String>

        // Fetches the device's serial number. Please note the purpose of this API is to administrate the device
        // (e.g. generating Certificate Sign Requests for device-wide certificates).
        // This API may not be used for tracking devices without the consent of the device's administrator.
        // If the current user is not affiliated, returns an empty string.
        // @return {callback.serialNumber}
        @ChromeMinVersion(66)
        @PromiseStyleMinVersion(96)
        fun getDeviceSerialNumber(
            callback: Value1Function<String>? = null
        )

        // Fetches the value of the device identifier of the directory API,
        // that is generated by the server and identifies the cloud record of the device for querying in the cloud directory API.
        // If the current user is not affiliated, returns an empty string.
        // @return {callback.deviceId}
        @PromiseStyleMinVersion(96)
        fun getDirectoryDeviceId(
            callback: Value1Function<String>? = null
        ): Promise<String>
    }

    ////////////////////
    // Enterprise Hardware Platform
    ////////////////////
    /**
     * Use the `Browser.enterprise.hardwarePlatform` API to get the manufacturer and model of the hardware platform where the browser runs.
     *
     * Permissions: "enterprise.hardwarePlatform"
     *
     * Note: Only available to policy installed extensions.
     * @since Chrome 71
     */
    @ChromeMinVersion(71)
    interface HardwarePlatform {
        // Obtains the manufacturer and model for the hardware platform and,
        // if the extension is authorized, returns it via callback.
        @PromiseStyleMinVersion(96)
        fun getHardwarePlatformInfo(
            callback: Value1Function<HardwarePlatformInfo>? = null
        ): Promise<HardwarePlatformInfo>

        data class HardwarePlatformInfo(
            var manufacturer: String,
            var model: String,
        )
    }

    ////////////////////
    // Enterprise Login
    ////////////////////
    /**
     * Use the `Browser.enterprise.login` API to exit Managed Guest sessions. Note: This API is only available to extensions installed by enterprise policy in ChromeOS Managed Guest sessions.
     *
     * Permissions: "enterprise.login"
     *
     * Note: Only available to policy installed extensions.
     * @platform ChromeOS only
     * @since Chrome 139
     */
    interface Login {
        /** Exits the current managed guest session. */
        fun exitCurrentManagedGuestSession(callback: VoidFunction? = null): Promise<Void>
    }

    ////////////////////
    // Enterprise Networking Attributes
    ////////////////////
    /**
     * Use the `Browser.enterprise.networkingAttributes` API to read information about your current network. Note: This API is only available to extensions force-installed by enterprise policy.
     *
     * Permissions: "enterprise.networkingAttributes"
     *
     * Note: Only available to policy installed extensions.
     * @platform ChromeOS only
     * @since Chrome 85
     */
    @ChromeMinVersion(85)
    @ChromeOSOnly
    interface NetworkingAttributes {
        // Retrieves the network details of the device's default network.
        // If the user is not affiliated or the device is not connected to a network,
        // runtime.lastError will be set with a failure reason.
        @PromiseStyleMinVersion(96)
        fun getNetworkDetails(
            callback: Value1Function<NetworkDetails>? = null
        ): Promise<NetworkDetails>

        data class NetworkDetails(
            // The device's local IPv4 address (undefined if not configured).
            var ipv4: String?,
            // The device's local IPv6 address (undefined if not configured).
            var ipv6: String?,
            // The device's MAC address.
            var macAddress: String,
        )
    }

    ////////////////////
    // Enterprise Platform Keys
    ////////////////////
    /**
     * Use the `Browser.enterprise.platformKeys` API to generate keys and install certificates for these keys. The certificates will be managed by the platform and can be used for TLS authentication, network access or by other extension through {@link Browser.platformKeys}.
     *
     * Permissions: "enterprise.platformKeys"
     *
     * Note: Only available to policy installed extensions.
     * @platform ChromeOS only
     */

    @ChromeOSOnly
    interface PlatformKeys {
        // Similar to challengeMachineKey and challengeUserKey,
        // but allows specifying the algorithm of a registered key.
        // Challenges a hardware-backed Enterprise Machine Key and emits the response as part of a remote attestation protocol.
        // Only useful on ChromeOS and in conjunction with the Verified Access Web API which both issues challenges and verifies responses.
        //
        //A successful verification by the Verified Access Web API is a strong signal that the current device is a legitimate ChromeOS device,
        // the current device is managed by the domain specified during verification,
        // the current signed-in user is managed by the domain specified during verification,
        // and the current device state complies with enterprise device policy.
        // For example, a policy may specify that the device must not be in developer mode.
        // Any device identity emitted by the verification is tightly bound to the hardware of the current device.
        // If "user" Scope is specified, the identity is also tightly bound to the current signed-in user.
        //
        //This function is highly restricted and will fail if the current device is not managed,
        // the current user is not managed, or if this operation has not explicitly been enabled for the caller by enterprise device policy.
        // The challenged key does not reside in the "system" or "user" token and is not accessible by any other API.
        // @return {callback.response}
        @ChromeMinVersion(110)
        @PromiseStyleMinVersion(131)
        fun challengeKey(
            // Object containing the fields defined in ChallengeKeyOptions.
            options: ChallengeKeyOptions,
            callback: Value1Function<ArrayBuffer>? = null
        ): Promise<ArrayBuffer>

        // Challenges a hardware-backed Enterprise Machine Key and emits the response as part of a remote attestation protocol.
        // Only useful on ChromeOS and in conjunction with the Verified Access Web API which both issues challenges and verifies responses.
        // A successful verification by the Verified Access Web API is a strong signal of all of the following:
        // * The current device is a legitimate ChromeOS device. *
        // The current device is managed by the domain specified during verification.
        // * The current signed-in user is managed by the domain specified during verification. *
        // The current device state complies with enterprise device policy.
        // For example, a policy may specify that the device must not be in developer mode.
        // * Any device identity emitted by the verification is tightly bound to the hardware of the current device.
        // This function is highly restricted and will fail if the current device is not managed,
        // the current user is not managed, or if this operation has not explicitly been enabled for the caller by enterprise device policy.
        // The Enterprise Machine Key does not reside in the "system" token and is not accessible by any other API.
        // @return {callback.response}
        @ChromeMinVersion(50)
        @Deprecated(
            "Deprecated since Chrome 110",
            replaceWith = ReplaceWith("Use challengeKey instead.")
        )
        @PromiseStyleMinVersion(131)
        fun challengeMachineKey(
            // A challenge as emitted by the Verified Access Web API.
            challenge: ArrayBuffer,
            @ChromeMinVersion(59)
            // If set, the current Enterprise Machine Key is registered with the "system" token and relinquishes the Enterprise Machine Key role.
            // The key can then be associated with a certificate and used like any other signing key.
            // This key is 2048-bit RSA. Subsequent calls to this function will then generate a new Enterprise Machine Key.
            registerKey: Boolean?,
            callback: Value1Function<ArrayBuffer>? = null
        ): Promise<ArrayBuffer>

        // Challenges a hardware-backed Enterprise Machine Key and emits the response as part of a remote attestation protocol.
        // Only useful on ChromeOS and in conjunction with the Verified Access Web API which both issues challenges and verifies responses.
        // A successful verification by the Verified Access Web API is a strong signal of all of the following:
        // * The current device is a legitimate ChromeOS device. *
        // The current device is managed by the domain specified during verification.
        // * The current signed-in user is managed by the domain specified during verification. *
        // The current device state complies with enterprise device policy.
        // For example, a policy may specify that the device must not be in developer mode.
        // * Any device identity emitted by the verification is tightly bound to the hardware of the current device.
        // This function is highly restricted and will fail if the current device is not managed,
        // the current user is not managed, or if this operation has not explicitly been enabled for the caller by enterprise device policy.
        // The Enterprise Machine Key does not reside in the "system" token and is not accessible by any other API.
        // @return {callback.response} The challenge response.
        @ChromeMinVersion(50)
        @Deprecated(
            "Deprecated since Chrome 110",
            replaceWith = ReplaceWith("Use challengeKey instead.")
        )
        @PromiseStyleMinVersion(131)
        fun challengeUserKey(
            // A challenge as emitted by the Verified Access Web API.
            challenge: ArrayBuffer,
            // If set, the current Enterprise Machine Key is registered with the "system" token and relinquishes the Enterprise Machine Key role.
            // The key can then be associated with a certificate and used like any other signing key.
            // This key is 2048-bit RSA. Subsequent calls to this function will then generate a new Enterprise Machine Key.
            registerKey: Boolean?,
            callback: Value1Function<ArrayBuffer>? = null
        ): Promise<ArrayBuffer>

        // Returns the list of all client certificates available from the given token.
        // Can be used to check for the existence and expiration of client certificates that are usable for a certain authentication.
        // @return {callback.certificates} The list of certificates, each in DER encoding of a X.509 certificate.
        @PromiseStyleMinVersion(131)
        fun getCertificates(
            // The id of a Token returned by getTokens.
            tokenId: String,
            callback: Value1Function<List<ArrayBuffer>>? = null
        ): Promise<List<ArrayBuffer>>

        // Returns the available Tokens. In a regular user's session the list will always contain the user's token with id "user".
        // If a system-wide TPM token is available,
        // the returned list will also contain the system-wide token with id "system".
        // The system-wide token will be the same for all sessions on this device (device in the sense of e.g. a Chromebook).
        // @return {callback.tokens} The list of available tokens.
        @PromiseStyleMinVersion(131)
        fun getTokens(
            callback: Value1Function<List<Token>>? = null
        ): Promise<List<Token>>

        // Imports certificate to the given token if the certified key is already stored in this token.
        // After a successful certification request,
        // this function should be used to store the obtained certificate and to make it available to the operating system and browser for authentication.
        @PromiseStyleMinVersion(131)
        fun importCertificate(
            // The id of a Token returned by getTokens.
            tokenId: String,
            // The DER encoding of a X.509 certificate.
            certificate: ArrayBuffer,
            callback: VoidFunction? = null
        ): Promise<Void>

        // Removes certificate from the given token if present.
        // Should be used to remove obsolete certificates so that they are not considered during authentication
        // and do not clutter the certificate choice.
        // Should be used to free storage in the certificate store.
        @PromiseStyleMinVersion(131)
        fun removeCertificate(
            // The id of a Token returned by getTokens.
            tokenId: String,
            // The DER encoding of a X.509 certificate.
            certificate: ArrayBuffer,
            callback: VoidFunction? = null
        ): Promise<Void>

        // Type of key to generate.
        @ChromeMinVersion(110)
        enum class Algorithm {
            RSA,
            ECDSA
        }

        @ChromeMinVersion(110)
        data class ChallengeKeyOptions(
            // A challenge as emitted by the Verified Access Web API.
            var challenge: ArrayBuffer,
            // If present, registers the challenged key with the specified scope's token.
            // The key can then be associated with a certificate and used like any other signing key.
            // Subsequent calls to this function will then generate a new Enterprise Key in the specified scope
            var registerKey: RegisterKeyOptions,
            // Which Enterprise Key to challenge.
            var scope: Scope,
        )

        @ChromeMinVersion(110)
        data class RegisterKeyOptions(
            // Which algorithm the registered key should use.
            var algorithm: Algorithm,
        )

        // Whether to use the Enterprise User Key or the Enterprise Machine Key.
        enum class Scope {
            USER,
            MACHINE,
        }

        data class Token(
            // Uniquely identifies this Token.
            //
            //Static IDs are "user" and "system",
            // referring to the platform's user-specific and the system-wide hardware token,
            // respectively.
            // Any other tokens (with other identifiers) might be returned by enterprise.platformKeys.getTokens.
            var id: String,
            // Implements the WebCrypto's SubtleCrypto interface.
            // The cryptographic operations, including key generation, are software-backed.
            // Protection of the keys, and thus implementation of the non-extractable property,
            // is done in software, so the keys are less protected than hardware-backed keys.
            //
            //Only non-extractable keys can be generated.
            // The supported key types are RSASSA-PKCS1-V1_5 and RSA-OAEP (on Chrome versions 135+) with modulusLength up to 2048.
            // Each RSASSA-PKCS1-V1_5 key can be used for signing data at most once,
            // unless the extension is allowlisted through the KeyPermissions policy,
            // in which case the key can be used indefinitely. RSA-OAEP keys are supported since
            // Chrome version 135 and can be used by extensions allowlisted through that same policy to unwrap other keys.
            //
            //Keys generated on a specific Token cannot be used with any other Tokens,
            // nor can they be used with window.crypto.subtle.
            // Equally, Key objects created with window.crypto.subtle cannot be used with this interface.
            @ChromeMinVersion(97)
            var softwareBackedSubtleCrypto: SubtleCrypto,
            // Implements the WebCrypto's SubtleCrypto interface.
            // The cryptographic operations, including key generation, are hardware-backed.
            //
            //Only non-extractable keys can be generated.
            // The supported key types are RSASSA-PKCS1-V1_5 and RSA-OAEP (on Chrome versions 135+) with modulusLength up to 2048 and ECDSA with namedCurve P-256.
            // Each RSASSA-PKCS1-V1_5 and ECDSA key can be used for signing data at most once,
            // unless the extension is allowlisted through the KeyPermissions policy,
            // in which case the key can be used indefinitely. RSA-OAEP keys are supported since
            // Chrome version 135 and can be used by extensions allowlisted through that same policy to unwrap other keys.
            //
            //Keys generated on a specific Token cannot be used with any other Tokens,
            // nor can they be used with window.crypto.subtle.
            // Equally, Key objects created with window.crypto.subtle cannot be used with this interface.
            var subtleCrypto: SubtleCrypto,
        )
    }
}